package com.zhu.classfile;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

//类字节码读取器
//buffer.get()        // 读 1 字节 → position += 1
//buffer.getShort()   // 读 2 字节 → position += 2
//buffer.getInt()     // 读 4 字节 → position += 4
public class ClassReader {
    private  ByteBuffer buffer;

    private ClassReader(byte[] classData) {
        this.buffer = ByteBuffer.wrap(classData);
        // 显式设置大端
        this.buffer.order(ByteOrder.BIG_ENDIAN);
    }

    public static ClassReader createClassReader(byte[] classData) {
        if (classData ==null || classData.length == 0) {
            throw new IllegalArgumentException("class data cannot be  empty");
        }
        return new ClassReader(classData);
    }
    //class 文件中的 u1 就是“无符号 8 位整数” 范围是 0 ~ 255 的整数，class 文件中的 u1 就是这种类型
    //JVM 规范中定义的 u1、u2、u4 中的 u 就是 unsigned 的意思
    public int readUint8() {
        return Byte.toUnsignedInt(buffer.get());
    }
    //buffer.getShort()：从 ByteBuffer 读取 2 个字节，返回 short（有符号 16 位）
    //Short.toUnsignedInt(short s)：把 short 当作无符号数，转换成 int
    //所以 readUint16 要从字节流中连续读取 2 个字节，并把它们组合成一个数字。
    public int readUint16() {
        return Short.toUnsignedInt(buffer.getShort());
    }
    //buffer.getInt()：读取 4 个字节，返回 int（有符号 32 位）
    //Integer.toUnsignedLong(int i)：把 int 当作无符号数，转换成 long
    public long readUint32 () {
        return Integer.toUnsignedLong(buffer.getInt());
    }
    //注意：Java 的 long 就是 64 位有符号
    public long readUint64() {
        return buffer.getLong();
    }

    //从 class 文件的字节流中读取一个由多个 u2（无符号 16 位整数）组成的数组
    public int[] readUint16s() {
        //从字节流中先读取一个 u2，这个值表示后面有多少个 u2 要读 [数量] [元素1] [元素2] ... [元素N]
        int count = readUint16();
        //创建一个长度为 count 的 int 数组
        //用于存储接下来要读取的 count 个 u2 值
        //例如：如果 count = 3，就创建 new int[3]
        int[] s = new int[count];
        for (int i = 0; i < count; i++) {
            //循环 count 次，每次调用 readUint16() 读取一个 u2
            //把读到的值存入数组 s 的对应位置
            s[i] = readUint16();
        }
        return s;
    }

    public byte[] readBytes(int length) {
        byte[] bytes = new byte[length];
        buffer.get(bytes);
        return bytes;
    }

}
